# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: xguo

import coin.proto.coin_market_enums_pb2 as coin_enum
from coin.exchange.base.order_gateway_log_builder import (prepare_builder,
                                                          to_proto_order_side,
                                                          to_proto_order_type,
                                                          BaseOrderEventBuilder)
from coin.exchange.base.order_gateway_logger import OrderGatewayLogProvider
from coin.proto.coin_order_gateway_pb2 import OrderEvent
import coin.proto.coin_order_enums_pb2 as coin_order


class OrderEventBuilder(BaseOrderEventBuilder):
  def set_order(self, order):
    internal_order_id = order.order_id
    external_order_id = order.internal.exchange_order_id
    order_price = order.price
    order_qty = order.qty
    order_side = to_proto_order_side(order.order_side)
    order_type = to_proto_order_type(order.order_type)

    self.oe.MergeFrom(
        OrderEvent(internal_order_id=internal_order_id,
                   external_order_id=str(external_order_id),
                   order_price=order_price,
                   order_qty=order_qty,
                   order_side=order_side,
                   order_type=order_type))


class SimpleOrderGatewayLogProvider(OrderGatewayLogProvider):
  def gen_order_submitted_event_and_log(self, order, timestamp):
    self.gen_order_request_and_order_event_and_log(
        symbol=order.product.native_symbol,
        order_price=order.price,
        order_qty=order.qty,
        order_side=order.order_side,
        order_type=order.order_type,
        internal_order_id=order.order_id,
        timestamp=timestamp,
    )

  def gen_order_filled_event_and_log(
      self,
      order,
      timestamp,
      *,
      fill_type=None,
      guess_fill_type=None,
  ):
    builder = prepare_builder(OrderEventBuilder,
                              None,
                              timestamp,
                              self.get_next_order_event_id(),
                              self.exchange_type,
                              order.product.native_symbol)
    builder.set_order(order)

    if order.internal.fill.fully_filled:
      order_state = coin_order.DEAD_ORDER
    else:
      order_state = coin_order.WORKING_ORDER
    builder.set_fill(
        fill_price=order.internal.fill.value.price_last_fill,
        fill_qty=order.internal.fill.value.qty_last_fill,
        fill_type=fill_type,
        guess_fill_type=guess_fill_type,
    )

    builder.set_state(order_event_type=OrderEvent.ORDER_FILLED,
                      order_state=order_state,
                      order_event_source=OrderEvent.EXCHANGE)
    self.write_order_event(builder.oe)

  def gen_order_event_and_log(self, order, timestamp, order_event_type):
    builder = prepare_builder(OrderEventBuilder,
                              None,
                              timestamp,
                              self.get_next_order_event_id(),
                              self.exchange_type,
                              order.product.native_symbol)
    builder.set_order(order)

    if order_event_type == OrderEvent.ORDER_ACCEPTED:
      order_state = coin_order.WORKING_ORDER
    elif order_event_type == OrderEvent.ORDER_REJECTED:
      order_state = coin_order.DEAD_ORDER
    elif order_event_type == OrderEvent.ORDER_ERROR:
      order_state = coin_order.DEAD_ORDER
    elif order_event_type == OrderEvent.CANCEL_ACCEPTED:
      order_state = coin_order.WORKING_ORDER
    elif order_event_type == OrderEvent.CANCEL_ERROR:
      order_state = coin_order.WORKING_ORDER
    elif order_event_type == OrderEvent.CANCEL_CONFIRMED:
      order_state = coin_order.DEAD_ORDER
    else:
      raise NotImplementedError()

    builder.set_state(order_event_type=order_event_type,
                      order_state=order_state,
                      order_event_source=OrderEvent.EXCHANGE)
    self.write_order_event(builder.oe)
